package device

import (
	"context"
	"log"
	"sync"
	"time"

	"gitee.com/yanwc/ebike-xiaoan-device/internal/field"
	"github.com/panjf2000/gnet"
)

type Key string

const (
	ImeiKey Key = "imei"
)

type Session struct {
	Device           *Device
	LoginTimeAt      time.Time
	heartBeatTicker  time.Ticker   // 心跳计时器
	HeartBeatTimeout time.Duration // 心跳超时时间
}

type Devices struct {
	mutex   sync.RWMutex
	devices map[field.IMEI]*Session
}

var SessionDevices Devices = Devices{
	devices: make(map[field.IMEI]*Session, 1000),
}

func (sd *Devices) Add(imei field.IMEI, d *Device) {
	sd.mutex.Lock()
	defer sd.mutex.Unlock()
	d.Conn.SetContext(context.WithValue(context.Background(), ImeiKey, imei))
	sd.devices[imei] = &Session{
		Device:      d,
		LoginTimeAt: time.Now(),
	}
	// 注册心跳超时计时器
	// TODO 注册到总线 imei:ip+port
}

func (sd *Devices) Remove(imei field.IMEI) {
	sd.mutex.Lock()
	defer sd.mutex.Unlock()
	if d, ok := sd.devices[imei]; ok {
		if err := d.Device.Conn.Close(); err != nil {
			log.Fatal(err)
		}
	}

	delete(sd.devices, imei)
}

func (sd *Devices) Get(imei field.IMEI) (*Device, bool) {
	sd.mutex.Lock()
	defer sd.mutex.Unlock()

	c, ok := sd.devices[imei]
	return c.Device, ok
}

func (sd *Devices) GetWithConn(c gnet.Conn) (*Device, bool) {
	ctx := c.Context()
	if ctx == nil {
		return nil, false
	}

	if v, ok := ctx.(context.Context); ok {
		imei, ok := v.Value(ImeiKey).(field.IMEI)
		if !ok {
			return nil, ok
		}
		sd.mutex.Lock()
		defer sd.mutex.Unlock()

		if v, ok := sd.devices[imei]; ok {
			return v.Device, ok
		} else {
			return nil, ok
		}
	}

	return nil, false
}
